//
// Created by wk on 23-5-21.
//

#ifndef HNUVISION_TCP_LOGGER_H
#define HNUVISION_TCP_LOGGER_H
#include <arpa/inet.h>
#include <chrono>
#include <fcntl.h>
#include <iostream>
#include <mutex>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <thread>
#include <unistd.h>

#define PORT 1234
#define QUEUE 20//连接请求队列

using namespace std::chrono_literals;


class TCP_Logger
{
public:
    TCP_Logger()
    {
        ss = socket(AF_INET, SOCK_STREAM, 0);
        server_sockaddr.sin_family = AF_INET;
        server_sockaddr.sin_port = htons(PORT);
        server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

        if (bind(ss, (struct sockaddr *) &server_sockaddr, sizeof(server_sockaddr)) == -1)
        {
            perror("bind");
            exit(1);
        }

        if (listen(ss, QUEUE) == -1)
        {
            perror("listen");
            exit(1);
        }

        socklen_t length = sizeof(client_sockaddr);
        printf("wait for connect\n");
        conn = accept(ss, (struct sockaddr *) &client_sockaddr, &length);
        if (conn < 0)
        {
            perror("connect");
            exit(1);
        }
    }

    ~TCP_Logger()
    {
        close(conn);
        close(ss);
    }

    void update(const std::string &data)
    {
        if (mtx.try_lock_for(1ms))
        {
            send_buf = data + "\n";
            mtx.unlock();
        }
    }

    void log()
    {
        if (mtx.try_lock_for(1ms))
        {
            int data_len = send_buf.length();
            if (data_len != 0)
            {
                if(send(conn, send_buf.c_str(), data_len, 0)<0)
                {
                    perror("send");
                    exit(1);
                }
                send_buf.clear();
            }
            mtx.unlock();
        }
    }

    void log(const std::string &data)
    {
        if(send(conn, data.c_str(), data.length(), 0)<0)
        {
            perror("send");
            exit(1);
        }
    }

private:
    int ss;
    int conn;

    struct sockaddr_in server_sockaddr;
    struct sockaddr_in client_sockaddr;

    std::string send_buf;
    std::timed_mutex mtx;
};
#endif//HNUVISION_TCP_LOGGER_H
